package com.kira.scaffoldmvc.CommonPool;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;


//ThreadLocal结合对象池,封装了对象池的相关操作
@Slf4j
public class RtaProxyContextHolder {

    private static final ThreadLocal<RtaLog> CONTEXT_HOLDER = new ThreadLocal<>();

    public static final GenericObjectPool<RtaLog> RTA_PROXY_CONTENT_POOL = new GenericObjectPool<>(
            new RtaProxyContextFactory(),//对象池工厂
            new GenericObjectPoolConfig<>() {{//对象池配置
                setMaxTotal(1000);//最大对象数
                setMaxIdle(600);//最大空闲对象数
                setMinIdle(200);//最小空闲对象数
            }});


    //自定义对象池工厂
    private static class RtaProxyContextFactory extends BasePooledObjectFactory<RtaLog> {

        //创建新对象
        @Override
        public RtaLog create() {
            return new RtaLog();
        }

        //负责将新创建或从其他地方获取的 RtaProxyContext 对象包装成 PooledObject<RtaProxyContext> 类型的对象
        // 这里使用 DefaultPooledObject 进行包装，以便对象池进行统一管理
        //将其他地方的对象(例如不是对象池创建的对象)转换成对象池对象实现复用
        @Override
        public PooledObject<RtaLog> wrap(RtaLog context) {
            return new DefaultPooledObject<>(context);
        }

        @Override
        public void destroyObject(PooledObject<RtaLog> p) {

            // 销毁对象的逻辑
        }
    }

    public static RtaLog getContext() {
        return CONTEXT_HOLDER.get();
    }

    public static RtaLog borrowContext() {

        RtaLog rtaLog;
        try {
            //先从对象池获取对象
            rtaLog = RTA_PROXY_CONTENT_POOL.borrowObject();
        } catch (Exception e) {
            //对象池获取对象失败,为了保证对象池可以成功创建,所以要new一个对象
            rtaLog = new RtaLog();
            log.warn("Failed to pull from pool");
        }
        //将详细的日志对象放到ThreadLocal里面
        CONTEXT_HOLDER.set(rtaLog);
        return rtaLog;
    }

    public static void returnContext(RtaLog context) {
        //将日志对象从ThreadLocal中移除
        CONTEXT_HOLDER.remove();

        //将原本的日志对象的大部分值变成空值
        if (context != null) {
            try {
                context.setReqXid("");
                context.setReqTime(-1);
                context.setRespTime(-1);
                context.setReqType("");
                context.setReqHeader("");
                context.setReqBody("");
                context.setRespBody("");
                context.setRespCode(-1);
                context.setErrorDetails("");
                context.setCached(false);
                RTA_PROXY_CONTENT_POOL.returnObject(context);
            } catch (Exception e) {
                log.warn("Failed to return to pool");
            }
        }
    }

    //日志打印对象池的状态
    public static void printPoolStatus() {
        log.info("Context Pool状态, 活跃对象数 {}, 空闲对象数 {}, 等待获取对象的线程数 {}, 对象创建总次数 {}, 对象销毁总次数 {}.",
                RTA_PROXY_CONTENT_POOL.getNumActive(),
                RTA_PROXY_CONTENT_POOL.getNumIdle(),
                RTA_PROXY_CONTENT_POOL.getNumWaiters(),
                RTA_PROXY_CONTENT_POOL.getCreatedCount(),
                RTA_PROXY_CONTENT_POOL.getDestroyedCount()
        );
    }


    // 动态调整对象池配置
    public static void adjustPoolConfig(int maxTotal, int maxIdle, int minIdle) {
        GenericObjectPoolConfig<RtaLog> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdle);
        config.setMinIdle(minIdle);
        // 应用新配置
        RTA_PROXY_CONTENT_POOL.setConfig(config);
        log.info("对象池配置已更新: maxTotal={}, maxIdle={}, minIdle={}", maxTotal, maxIdle, minIdle);
    }

}




